class Hooker {
    constructor(context) {
        this._hooker = {};
        this._remote = null;
        this._local = null;
        this._util = null;
        this._context = context || {};
    }

    setContext(key, value) {
        if (arguments.length === 1) {
            Object.assign(this._context, key || {});
        } else {
            this._context[key] = value;
        }
        return this;
    }

    hook(type, fn) {
        if (!this._hooker[type]) {
            this._hooker[type] = [];
        }
        if (!this._hooker[type].includes(fn)) {
            this._hooker[type].push(fn);
        }
        return this;
    }

    emit(type, data = {}) {
        let context = {
            data,
            error: null,
            env: this._context
        };
        return (this._hooker[type] || []).reduce((a, fn) => {
            return a.then(() => {
                return Promise.resolve().then(() => {
                    return fn(context);
                }).then(() => {
                    return context.data;
                }).catch(e => {
                    // console.log(e);
                    context.error = e;
                    return context.data;
                });
            });
        }, Promise.resolve()).then(() => {
            return context.data;
        });
    }

    has(type) {
        return this._hooker[type] && this._hooker[key].length > 0;
    }
};

module.exports = Hooker;